package com.hhf.rpc.core.handler;

import com.hhf.rpc.core.RpcApplication;
import com.hhf.rpc.core.config.RpcConfig;
import com.hhf.rpc.core.model.RpcRequest;
import com.hhf.rpc.core.model.RpcResponse;
import com.hhf.rpc.core.registry.LocalRegistry;
import com.hhf.rpc.core.serializer.Serializer;
import com.hhf.rpc.core.serializer.SerializerFactory;
import com.hhf.rpc.core.serializer.impl.JdkSerializer;
import io.vertx.core.Handler;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.lang.reflect.Method;

/**
 * @Author hhf
 * @Date 2024/10/15
 * @Description 自定义请求处理器
 */
@Slf4j
public class HttpServerHandler implements Handler<HttpServerRequest> {

    @Override
    public void handle(HttpServerRequest request) {

        RpcConfig rpcConfig = RpcApplication.getRpcConfig();
        String serializerKey = rpcConfig.getSerializerKey();
        Serializer serializer = SerializerFactory.getSerializerInstance(serializerKey);

        log.info("vertx服务器接收到请求\n请求方法:{}\n请求地址:{}", request.method(), request.uri());

        //异步调用
        request.bodyHandler(body -> {
            //1.获取请求体的数据 byte[]
            byte[] bytes = body.getBytes();
            //2.反序列化 byte[] -> RpcRequest
            RpcRequest rpcRequest = null;
            try {
                rpcRequest = serializer.deSerialize(bytes, RpcRequest.class);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            //3.构造响应体 RpcResponse
            RpcResponse rpcResponse = new RpcResponse();
            if (rpcResponse == null){
                rpcResponse.setMessage("rpcResponse is null");
                doResponse(request, rpcResponse, serializer);
                return;
            }
            //4.根据请求的serviceName和methodName找对应的实现类,进行调用(反射原理)
            try {
                Class<?> implClass = LocalRegistry.get(rpcRequest.getServiceName());
                Method method = implClass.getMethod(rpcRequest.getMethodName(), rpcRequest.getParameterTypes());
                Object invoke = method.invoke(implClass.getDeclaredConstructor().newInstance(), rpcRequest.getArgs());
                //封装结果
                rpcResponse.setMessage("ok");
                rpcResponse.setData(invoke);
                rpcResponse.setDataType(method.getReturnType());
            } catch (Exception e) {
                e.printStackTrace();
                rpcResponse.setException(e);
                rpcResponse.setMessage(e.getMessage());
            }
            doResponse(request, rpcResponse, serializer);
        });

    }

    private void doResponse(HttpServerRequest request, RpcResponse rpcResponse, Serializer serializer) {
        //序列化 RpcResponse -> byte[]
        HttpServerResponse httpServerResponse = request.response().putHeader("content-type", "text/plain");

        try {
            byte[] bytes = serializer.serialize(rpcResponse);
            httpServerResponse.end(Buffer.buffer(bytes));
        } catch (IOException e) {
            e.printStackTrace();
            httpServerResponse.end(Buffer.buffer());
        }


    }
}
